#!../sl

:- import "%%/lib/os.sl" #


generate .outFile :-
	stream.writeFile OUT.SL.FILE .outFile,
--	stream.stdout OUT.SL.FILE,
	set OUTPUT OUT.SL.FILE,
	forall (file.each "*.ssp" .filename) (generate.ssp .filename),
	stream.close OUT.SL.FILE #

generate.ssp .filename :-
	stream.readFile IN.SSP.FILE .filename,
	setPredicateName .filename
	,
	set INPUT IN.SSP.FILE,
	set STATE HTML
	!
	(
		stream.while IN.SSP.FILE,
		get STATE .state,
		scanAtState .state;
		get STATE .state,
		whatever (endState .state NONE) -- Ends last state properly
	)
	,
	stream.close IN.SSP.FILE #

changeState .state :-
	get STATE .state0,
	whatever (endState .state0 .state),
	set STATE .state,
	whatever (beginState .state),
	fail # -- Enforces state change

doData .line :-
	get STATE .state, whatever (doData .state .line) #

doData . "" :- ! #

doNl :- get STATE .state, whatever (doNl .state) #

scanAtState HTML :- ssp.scanCode "" "" #
doData HTML .html :-
	writePredicateName,
	stream.createBuffer .buf,
	stream.write .buf "	www",
	stream.dump .buf .html,
	stream.write .buf ",",
	stream.line .buf .out,
	stream.close .buf,
--	concat "	www """ .html """," .out,
	writeToPage .out,
	set EMPTY.LINE NO #
doNl HTML :-
	inPredicate,
	get EMPTY.LINE NO,
	writeToPage "	wnl,",
	set EMPTY.LINE YES #
endState HTML .next :-
	.next = PROG; .next = VAR.OUT; -- Do not close before substates
	get PRED.DEF (END .), writeToPage "#", unset PRED.DEF #

scanAtState PROG :- ssp.scanCode "" "" #
doData PROG .prog :-
	writePredicateName,
	writeToPage .prog #

scanAtState VAR.OUT :- ssp.scanCode "" "" #
doData VAR.OUT .var :-
	concat "	www " .var "," .out,
	writeToPage .out #

beginState QUERY :- writeToPage ":-" #
scanAtState QUERY :- ssp.scanCode "" "" #
doData QUERY .query :- writeToPage .query #
endState QUERY . :- writeToPage "#" #

scanAtState ASSERT :- ssp.scanCode "" "" #
doData ASSERT .query :- writeToPage .query #
endState ASSERT . :- writeToPage "#" #

scanAtState NEW.PRED :- ssp.scanCode "" "" #
doData NEW.PRED .name :-
	concat .name " :-" .line,
	set PRED.DEF (START .line) #

ssp.scanCode .ch .acc :-
	nextChar .ch1;
	not (.acc = ""), .ch1 = "" -- Do the remaining data after EOF
	!
	concat .ch .ch1 .sym,
	select (.sym = "<<" =>
		doData .acc,
		nextChar .ch2,
		select
			(.ch2 = "=" => changeState VAR.OUT)
			(.ch2 = "?" => changeState QUERY)
			(.ch2 = "@" => changeState ASSERT)
			(.ch2 = ":" => changeState NEW.PRED)
			(changeState PROG) -- Note we would fail
	) (.sym = ">>" =>
		doData .acc, changeState HTML, fail
	) (ascii .ch 10 => -- Do a flush
		doData .acc,
		doNl,
		ssp.scanCode .ch1 ""
	) (
		concat .acc .ch .acc1, ssp.scanCode .ch1 .acc1
	) #

setPredicateName .filename :-
	concat "web." .filename " :-" .line,
	set PRED.DEF (START .line) #

writePredicateName :-
	whatever (
		get PRED.DEF (START .line),
		writeToPage .line,
		set PRED.DEF (END .line)
	) #

inPredicate :- get PRED.DEF (END .) #

writeToPage .line :-
	get OUTPUT .stream,
	stream.write .stream .line, stream.nl .stream #

nextChar .char :-
	get INPUT .stream, stream.get .stream .char #

:- generate "web.sl", quit #
